package cn.uncode.springcloud.starter.canary.api;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.springframework.util.ObjectUtils;

import cn.uncode.springcloud.starter.canary.properties.CanaryProperties;
import cn.uncode.springcloud.starter.canary.ribbon.support.RibbonContext;
import cn.uncode.springcloud.utils.net.WebUtil;

/**
 * 默认灰度策略，包括ip和参数in request and session
 * 
 * @author juny
 * @date 2019年4月26日
 *
 */
public class DefaultCanaryStrategy implements CanaryStrategy {
	
	private boolean enabled = false;
	
	private Map<String, StrategyModel> StrategyList = new HashMap<>();
	
	private Map<String, String> ip2flag = new HashMap<>();
	
	private Map<String, Set<String>> keyInRequest2value = new HashMap<>();
	
	private Map<String, String> keyInRequest2flag = new HashMap<>();
	
	private Map<String, Set<String>> keyInSession2value = new HashMap<>();
	
	private Map<String, String> keyInSession2flag = new HashMap<>();
	
	/**
	 * 构造并解析配置信息
	 * @param canaryProperties
	 */
	public DefaultCanaryStrategy(CanaryProperties canaryProperties) {
		if(!ObjectUtils.isEmpty(canaryProperties)) {
			if(canaryProperties.isEnabled()) {
				this.enabled = true;
				if(null != canaryProperties.getStrategy()) {
					for(StrategyModel item:canaryProperties.getStrategy()) {
						StrategyList.put(item.getFlag(), item);
						if(DEFAULT_STRATEGY_TYPE_IP.equals(item.getType())) {
							Set<String> sets = item.getValue();
							for(String str:sets) {
								ip2flag.put(str, item.getFlag());
							}
						}else if(DEFAULT_STRATEGY_TYPE_REQUEST.equals(item.getType())) {
							keyInRequest2value.put(item.getKey(), item.getValue());
							keyInRequest2flag.put(item.getKey(), item.getFlag());
						}else if(DEFAULT_STRATEGY_TYPE_SESSION.equals(item.getType())) {
							keyInSession2value.put(item.getKey(), item.getValue());
							keyInSession2flag.put(item.getKey(), item.getFlag());
						}
					}
				}
			}
		}
	}
	
	/**
	 * 解析canaryFlag
	 */
	@Override
	public RibbonContext resolve(HttpServletRequest request) {
		RibbonContext ribbonContext = new RibbonContext();
		if(enabled) {
			//1查结果
			RibbonContext rcHeader = getRibbonContextFromHeader(request);
			if(rcHeader != null) {
				ribbonContext.setCanaryFlag(rcHeader.getCanaryFlag());
				return ribbonContext;
			}
			//2解析
			String flag = null;
			String ip = WebUtil.getIP(request);
			if(ip2flag.containsKey(ip)) {
				flag = ip2flag.get(ip);
			}else {
				for(Entry<String, Set<String>> item:keyInRequest2value.entrySet()) {
					Object value = WebUtil.getRequest().getParameter(item.getKey());
					if(null != value) {
						String val = String.valueOf(value);
						if(item.getValue().contains(val)) {
							flag = keyInRequest2flag.get(item.getKey());
						}
					}
				}
				for(Entry<String, Set<String>> item:keyInSession2value.entrySet()) {
					Object value = WebUtil.getRequest().getSession().getAttribute(item.getKey());
					if(null != value) {
						String val = String.valueOf(value);
						if(item.getValue().contains(val)) {
							flag = keyInSession2flag.get(item.getKey());
						}
					}
				}
			}
			if(StringUtils.isNotBlank(flag)) {
				ribbonContext.setCanaryFlag(flag);
			}
		}
		return ribbonContext;
	}
	
	private RibbonContext getRibbonContextFromHeader(HttpServletRequest request) {
		RibbonContext ribbonContext = null;
		String canaryFlag = request.getHeader(CanaryStrategy.FEIGN_CANARY_HEAD_KEY);
		if(StringUtils.isNotBlank(canaryFlag)) {
			ribbonContext = new RibbonContext();
			ribbonContext.valueOf(canaryFlag.trim());
		}
		return ribbonContext;
	}


}
